package com.ljph.kit;

import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.TableMapping;
import com.ljph.common.AppConfig;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by yuzhou on 16/8/6.
 */
public class CommonKit {

    private static final Logger _log = LoggerFactory.getLogger(CommonKit.class);

    public static String formatDecimal(BigDecimal value) {
      return formatDecimal(value, "#.00");
    }

    public static String formatDecimal(BigDecimal value, String format) {
      java.text.DecimalFormat df = new java.text.DecimalFormat(format);
      return df.format(value);
    }

    /**
     * UUID 字符串
     */
    public static String uuid() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 根据当前时间计算一个ID 用于系统业务数据的编号，总长度15位，规则如下：
     *  年的后两位+ 月份两位 + 日两位 + 当前时间在本日的秒数5位 + 当前毫秒数3位 + 业务相关或者随机数 1位
     * @param n
     * @return
     */
    public static String getUniqueId(long n) {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DAY_OF_MONTH);

        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);
        int second = calendar.get(Calendar.SECOND);

        int seconds = hour * 3600 + minute * 60 + second;
        int ms = calendar.get(Calendar.MILLISECOND);

        return String.format("%02d%02d%02d%05d%03d%d", year % 2000, month, day,
        seconds, ms, n % 10);
    }

    public static String getDateStr() {
      Calendar calendar = Calendar.getInstance();
      int year = calendar.get(Calendar.YEAR);
      int month = calendar.get(Calendar.MONTH) + 1;
      int day = calendar.get(Calendar.DAY_OF_MONTH);
      return String.format("%04d%02d%02d", year , month, day);
    }


    public static String getTableName(Class<? extends Model> modelClass) {
        return TableMapping.me().getTable(modelClass).getName();
    }

    public static String readStreamContent(InputStream is) throws IOException {

        byte[] c2 = new byte[1024];

        int n = 0;

        StringBuffer content = new StringBuffer();
        while((n = is.read(c2)) > 0) {
            content.append(new String(c2, 0, n, "UTF-8"));
        };

        return content.toString();
    }

    public static boolean runProcess(Object cmdString) {

        _log.debug("Run process with: " + cmdString);

        try {
          Runtime runTime = Runtime.getRuntime();

          Process process = null;
          if(cmdString instanceof String) {
            process = runTime.exec((String) cmdString);
          } else if(cmdString instanceof List) {
            process = runTime.exec(((List<String>)cmdString).toArray(new String[0]));
          }

          if(!checkProcessOutput(process)) {
            return false;
          }

        } catch (IOException e) {
            _log.error("Run process failed: ", e);
            return false;
        }

        _log.debug("Run successfully: over");
        return true;
    }

  private static boolean checkProcessOutput(Process process) throws IOException {

    String processOutput = readStreamContent(process.getInputStream());
    String processError = readStreamContent(process.getErrorStream());

    _log.debug("The normal output of process: \n" + processOutput);

    if(!processError.isEmpty()) {
      String errLines[] = processError.split("\\r?\\n");

      int ignored = 0;
      for(String line : errLines) {

        if(line.startsWith("Cleaning up unclosed ZipFile")) {
          _log.warn("Error: " + line + " is ignored");
          ignored++;
        }
      }

      if(ignored < errLines.length) {
        _log.error("Error occured when process executed: \n" + processError);
        return false;
      }
    }

    return true;
  }

  /**
   * 删除文件与目录
   * @param file
   * @throws IOException
   */
  public static void delete(File file)
    throws IOException{

    if(file.isDirectory()){

      //directory is empty, then delete it
      if(file.list().length==0){

        file.delete();
        System.out.println("Directory is deleted : "
          + file.getAbsolutePath());

      }else{

        //list all the directory contents
        String files[] = file.list();

        for (String temp : files) {
          //construct the file structure
          File fileDelete = new File(file, temp);

          //recursive delete
          delete(fileDelete);
        }

        //check the directory again, if empty then delete it
        if(file.list().length==0){
          file.delete();
          System.out.println("Directory is deleted : "
            + file.getAbsolutePath());
        }
      }

    }else{
      //if file, then delete it
      file.delete();
      System.out.println("File is deleted : " + file.getAbsolutePath());
    }
  }
  
  public static boolean sendSms(String mobile, String content, Map<String, Object> repMap) {

    _log.debug("Send short message to {} with content: {}", mobile, content);
    HttpClient client = new HttpClient();
    client.getParams().setContentCharset("UTF-8");

    PostMethod method = new PostMethod("http://106.ihuyi.cn/webservice/sms.php?method=Submit");
    method.setRequestHeader("ContentType", "application/x-www-form-urlencoded;charset=UTF-8");
    NameValuePair[] data = { // 提交短信
        new NameValuePair("account", "cf_ljkj"), new NameValuePair("password", "u6NrJ8"), // 密码可以使用明文密码或使用32位MD5加密
        // new NameValuePair("password",
        // util.StringUtil.MD5Encode("密码")),
        new NameValuePair("mobile", mobile), new NameValuePair("content", content), };
    method.setRequestBody(data);

    try {
      client.executeMethod(method);

      String submitResult = method.getResponseBodyAsString();
      _log.debug("The response data of send sms: \n" + submitResult);
      Document doc = DocumentHelper.parseText(submitResult);
      Element root = doc.getRootElement();
      String code = root.elementText("code");
      String msg = root.elementText("msg");
      String smsid = root.elementText("smsid");

      repMap.put("code", code);
      repMap.put("msg", msg);
      repMap.put("smsid", smsid);

      if (!code.equals("2")) {
        _log.error("Fail to send short message due to: " + msg);
        return false;
      } else {
        _log.info("The short message id is:" + smsid);
      }
    } catch (Exception e) {
      _log.error("Fail to send short message: ", e);
      return false;
    }

    return true;
  }
  
  public static String getRemoteAddrIp(HttpServletRequest request) {
    String ipFromNginx = getHeader(request, "X-Real-IP");
    return StrKit.notBlank(ipFromNginx) ? ipFromNginx : request
            .getRemoteAddr();
  }
  
  private static String getHeader(HttpServletRequest request, String headName) {
    String value = request.getHeader(headName);
    return StrKit.notBlank(value) && !"unknown".equalsIgnoreCase(value) ? value
            : "";
  }
  
  public static String filterEmoji(String str){
    if(StrKit.notBlank(str)){
      String pattern="[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]";  
      Pattern emoji = Pattern.compile(pattern);  
      Matcher emojiMatcher = emoji.matcher(str);  
      str = emojiMatcher.replaceAll(""); 
      return str;
    }
    return str;
  }
  
}
